#ifndef __H_MVP_TRANSPORT_LCM_PROXY_H__
#define __H_MVP_TRANSPORT_LCM_PROXY_H__

#include <memory>
#include <thread>

#include "common/macros.h"
#include "lcm-cpp.hpp"

namespace motovis {
namespace transport {

template <typename MessageT>
class LcmReceiver;

class LcmProxy
{
public:
    virtual ~LcmProxy();

    template <typename MessageT>
    bool publish(const std::string& channel_name, const std::shared_ptr<MessageT>& msg);

    template <typename MessageHandlerClass>
    void subscribe(const std::string& channel_name,
                   void (MessageHandlerClass::*handlerMethod)(const lcm::ReceiveBuffer *r_buf,
                                                              const std::string& channel),
                   MessageHandlerClass* handler);

private:
    void exec();

    lcm::LCM lcm_;
    std::shared_ptr<std::thread> thread_;

    DECLARE_SINGLETON(LcmProxy)
};

template <typename MessageT>
bool LcmProxy::publish(const std::string& channel_name, const std::shared_ptr<MessageT>& msg)
{
    return (lcm_.publish(channel_name, msg.get(), sizeof(MessageT)) == 0);
}

template <typename MessageHandlerClass>
void LcmProxy::subscribe(const std::string& channel_name,
               void (MessageHandlerClass::*handlerMethod)(const lcm::ReceiveBuffer *r_buf,
                                                          const std::string& channel),
               MessageHandlerClass* handler)
{
    lcm_.subscribe(channel_name, handlerMethod, handler);
}

} // namespace transport
} // namespace motovis

#endif // __H_MVP_TRANSPORT_LCM_PROXY_H__
